package control.MIC;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import algorithm.SAElem;
import control.CtrlEngine;
import control.ExeCtx;
import control.PerfEvaluator;
import control.RelbEvaluator;
import control.SAModifier;
import control.SASolver;
import foundation.fileUtil.TxtFileUtil;
import foundation.fileUtil.XMLmodifyUtil;
import foundation.pcmUtil.SimulatorMouse;

public class MICCtrlEngine extends CtrlEngine {
	protected MICCtrlEngHelper hlper=null;
	protected ExeCtx ctx=null;
	protected Random random = new Random();
	protected String initPopuPath = null;

	public MICCtrlEngine(ExeCtx exeCtx, SAModifier saMdfier, PerfEvaluator perfElvor, RelbEvaluator relbElvor) {
		super(exeCtx, saMdfier, perfElvor, relbElvor);
		hlper=new MICCtrlEngHelper(exeCtx);
        this.ctx=exeCtx;
        String basePath=ctx.getRunBasePath();
		initPopuPath =  basePath+ "jssbrsInitPopu.txt";
	}
	public void solve(){
		SASolver saSolver = SASolver.getInstance();
		saSolver.RunPCMSolver();
	}
	@Override
	public List<StringBuffer> getObjVals(List<StringBuffer> codes) {
		File file = new File("/root/git/cases/other cases/MiCforJSS-2tier/space4cloud");
		TxtFileUtil.deleteAllFilesOfDir(file);
		exeCtx.setCurFdCodes(codes);
		XMLmodifyUtil.modifyfile(codes);
		File file1 = new File("/root/git/cases/other cases/MiCforJSS-2tier/space4cloud/1.txt");
		if (file1.exists()) {
			file1.delete();
		}
		solve();
		List<StringBuffer> objVals=null;
		while (true) {
			if (file1.exists()) {
				objVals = readIndice();
				break;
			}else {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				file1= new File("/root/git/cases/other cases/MiCforJSS-2tier/space4cloud/1.txt");
			}
		}
		return objVals;
	}

	@Override
	public float getCost(List<StringBuffer> fdCodes) {
		isLegalCodes(fdCodes);
		float costIndice = 0;
		List<String> srvNames = new ArrayList<String>();
		for (int i = 4; i < 13; i++) {
			String srvName = fdCodes.get(i).toString();
			srvNames.add(srvName);
		}

		List<Float> spds = new ArrayList<Float>();
		for (int i = 0; i < 4; i++) {
			float speed = Float.parseFloat(fdCodes.get(i).toString());
			spds.add(speed);
		}

		List<String> alloSrvNames = new ArrayList<>();
		alloSrvNames.add(srvNames.get(0));
		for (int i = 1; i < srvNames.size(); i++) {
			for (int j = 0; j < alloSrvNames.size(); j++) {
				if (srvNames.get(i).equals(alloSrvNames.get(j))) {
					break;
				} else if (j == alloSrvNames.size() - 1) {
					alloSrvNames.add(srvNames.get(i));
				}

			}
		}
		System.out.println(alloSrvNames);
		for (String tempSrv : alloSrvNames) {
			String tempSrv2 = tempSrv.toString().trim();
			int len = tempSrv2.length();
			int SvrNo = Integer.parseInt(tempSrv2.substring(len - 1));

			costIndice += 0.7665f * Math.pow(spds.get(SvrNo - 1) / 10 * 1.5f, 6.2539f) + 145;
		}

		// ������WebServer���������������
		String curWebServer = fdCodes.get(13).toString();
		if (curWebServer.equals("WebServer")) {
			costIndice += 100f;
		} else if (curWebServer.equals("WebServer2")) {
			costIndice += 150f;
		} else if (curWebServer.equals("WebServer3")) {
			costIndice += 80f;
		}

		return costIndice;
	}

	@Override
	public ArrayList<SAElem> getChgedElems(List<StringBuffer> codes) {
		return hlper.getChgedElems(codes);
	}

	@Override
	/**
	 * ���������������������server1-4������server������ ���������������5.0-20.0������ 9������������������������4���server���
	 * Webserver���������WebServer2���WebServer3������
	 */
	public List<StringBuffer> getRndCodes() {
		 List<StringBuffer> codes = new ArrayList<StringBuffer>();
		 //������4���������������
		 int VMType =  1+ random.nextInt(82);
		 StringBuffer sVMType = new StringBuffer(String.valueOf(VMType));
		 codes.add(sVMType);
		 for(int i=0;i<48;i++){
		 int VMNumber =  1+ random.nextInt(5);
		 StringBuffer sVMNumber = new StringBuffer(String.valueOf(VMNumber));
		 codes.add(sVMNumber);
		 }
		 return codes;
	}

	@Override
	public List<StringBuffer> mutate(int mutateNum, List<StringBuffer> codes, Random random, float mutatePorb) {

		List<StringBuffer> newCodes = new ArrayList<StringBuffer>();
		// ���������������������
		int chromLen = codes.size();
		// ������������������������������
		for (int i = 0; i < chromLen; i++) {
			StringBuffer tmpStrBf = new StringBuffer(codes.get(i));
			newCodes.add(tmpStrBf);
		}

		/*
		 * ���������������������������������
		 */
		for (int i = 0; i < chromLen; i++) {
			float randomNum = random.nextFloat();

			if (randomNum < mutatePorb) {
				if (i >= 0 && i < 4) {
					float procSpd = 5 + random.nextInt(15) + random.nextFloat();
					StringBuffer spd = new StringBuffer(String.valueOf(procSpd));
					newCodes.set(i, spd);
				}
				if (i >= 4 && i < 13) {
					String srvName = "server" + String.valueOf(random.nextInt(4) + 1);
					StringBuffer serverName = new StringBuffer(srvName);
					newCodes.set(i, serverName);
				}
				if (i == 13) {
					List<String> webSvrNames = new ArrayList<String>();
					webSvrNames.add("WebServer");
					webSvrNames.add("WebServer2");
					webSvrNames.add("WebServer3");
					String nxtWebSvr = webSvrNames.get(random.nextInt(3));
					StringBuffer webSvr = new StringBuffer(nxtWebSvr);
					newCodes.set(i, webSvr);
				}
			}
		}
		return newCodes;
	}

	@Override
	public boolean isLegalCodes(List<StringBuffer> codes) {
		boolean isLegal = false;
		String alloWebSvr = codes.get(4).toString();
		String alloDB = codes.get(6).toString();
		if (alloWebSvr.equals("server1") && (alloDB.equals("server1") || alloDB.equals("server3"))) {
			isLegal = true;
		} else {
			isLegal = false;
		}
		return isLegal;
	}

	@Override
	public List<StringBuffer> repairCodes(List<StringBuffer> codes) {

		List<StringBuffer> afCodes = new ArrayList<StringBuffer>();
		for (int i = 0; i < 14; i++) {
			StringBuffer tmpStrBf = new StringBuffer(codes.get(i));
			afCodes.add(tmpStrBf);
		}
		// ������WebServer������
		if (!afCodes.get(4).toString().equals("server1")) {
			afCodes.set(4, new StringBuffer("server1"));
		}

		// ������DataBase������
		String alloDB = codes.get(6).toString();
		if (!(alloDB.equals("server1") || alloDB.equals("server3"))) {
			String srvDB = "server" + String.valueOf(2 * random.nextInt(2) + 1);
			StringBuffer serverDB = new StringBuffer(srvDB);
			afCodes.set(6, serverDB);
		}
		return afCodes;
	}

	public static void main(String[] args) {
//		String basePath="demo/jssbrs/runFiles/resultFile/";
//		String srcPath="demo/jssbrs/runFiles/initialSA/";
//		String UsageScenarioProer = "UsageScenario_BRS_usage_scenario_1_Processor";
//		
//		String relFlNm=basePath + "reliabilityRlt.markovresult";
		
		/*
		ExeCtx  ctx=new ExeCtx(srcPath,basePath,"brs",UsageScenarioProer,relFlNm);
		JssBRSCtrlEngHelper hlper=new JssBRSCtrlEngHelper(ctx);
		JssBRSCtrlEngine jssBRSCtrlEngine = new JssBRSCtrlEngine(hlper);
		for (int i = 0; i < 30; i++) {
			List<StringBuffer> codes = jssBRSCtrlEngine.getRndCodes();
			System.out.println(codes);
		}*/
		// float costIndice = jssBRSCtrlEngine.getCost(codes);
		// System.out.println(costIndice);
	}

	
	
	
}
